/*
 * YUYV转换成bmp模块
 */

#include "../include/yuvtobmp.h"
#include "../include/mydata.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

/*
 * YUV4：2：2转RGB
 * y0 cb0 y1 cr0 ---> r0 g0 b0 r1 g1 b1 
 * r0 = YCbCrtoR(y0, cb0, cr0);
 * g0 = YCbCrtoG(y0, cb0, cr0);
 * b0 = YCbCrtoB(y0, cb0, cr0);
 * r1 = YCbCrtoR(y1, cb0, cr0);
 * g1 = YCbCrtoG(y1, cb0, cr0);
 * b1 = YCbCrtoB(y1, cb0, cr0);
 * YUYV转RGB公式
 */
#if 0
#define YCbCrtoR(Y,Cb,Cr) ((Y) + 1.370705*(Cr-128))
#define YCbCrtoG(Y,Cb,Cr) ((Y) - 0.337633*(Cb-128) - 0.698001*(Cr-128))
#define YCbCrtoB(Y,Cb,Cr) ((Y) + 1.732446*(Cb-128))
#endif

#define YCbCrtoR(Y,Cb,Cr) ((Y) + 1.402*(Cr-128))
#define YCbCrtoG(Y,Cb,Cr) ((Y) - 0.34413*(Cb-128) - 0.71414*(Cr-128))
#define YCbCrtoB(Y,Cb,Cr) ((Y) + 1.772*(Cb-128))

static RGB24 rgb24;
static BMP   bmp24;

/*初始化及分配空间*/
void init_conv(u32 w, u32 h)
{
	/*初始化*/
	rgb24.len = w*h*3;
	bmp24.len = sizeof(BMPFILEHEADER) + sizeof(BMPINFOHEADER) + rgb24.len;
	
	rgb24.buf = (u8 *)malloc(rgb24.len);
	assert(NULL != rgb24.buf);
	
	bmp24.buf = (u8 *)malloc(bmp24.len);
	assert(NULL != bmp24.buf);
}

/*释放空间*/
void uninit_conv()
{		
	if(rgb24.buf)
		free(rgb24.buf);
		
	if(bmp24.buf)
		free(bmp24.buf);
		
	rgb24.len= 0;
	bmp24.len= 0;
	
	rgb24.buf = NULL;
	bmp24.buf = NULL;
}


 /*
 *功能：YUYV转RGB24函数
 *输入：
 *	u8 *yuv：v4l2_buffer的首地址
 *	u32 w：摄像头采集图片宽
 *	u32 h：摄像头采集图片高
 *输出：
 *	u8 * rgb24缓存首地址
 */
u8 * yuv_to_rgb24(u8 *yuv, u32 w, u32 h)
{
#if 1
	u8 y0,cb0,y1,cr0;
	int r, g, b;
	
	int len  = w*h*2;
	u8 *prgb = rgb24.buf;

	len /= 4;
	while(len--)
	{
		y0  = *yuv++;
		cb0 = *yuv++;
		y1  = *yuv++;
		cr0 = *yuv++;
	
		r = YCbCrtoR(y0, cb0, cr0);
		g = YCbCrtoG(y0, cb0, cr0);
		b = YCbCrtoB(y0, cb0, cr0);
	
		if (r > 255) r = 255;
		if (r < 0  ) r = 0;
		if (g > 255) g = 255;
		if (g < 0  ) g = 0;
		if (b > 255) b = 255;
		if (b < 0  ) b = 0;
	 
	 	*prgb++ = r;
		*prgb++ = g;
		*prgb++ = b;

		r = YCbCrtoR(y1, cb0, cr0);
		g = YCbCrtoG(y1, cb0, cr0);
		b = YCbCrtoB(y1, cb0, cr0);

		if (r > 255) r = 255;
		if (r < 0  ) r = 0;
		if (g > 255) g = 255;
		if (g < 0  ) g = 0;
		if (b > 255) b = 255;
		if (b < 0  ) b = 0;
	  
	 	*prgb++ = r;
		*prgb++ = g;
		*prgb++ = b;
	}
	return rgb24.buf;
#endif

}


 /*
 *功能：获取rgb24缓存大小
 *输入：
 *输出：
 *		rgb24缓存len
 */
 
int get_rgb24_len()
{
	return rgb24.len;
}

 /*
 *功能：YUYV转bmp函数
 *输入：
 *	u8 *yuv：v4l2_buffer的首地址(yuv）
 *	u32 w：摄像头采集图片宽
 *	u32 h：摄像头采集图片高
 *输出：
 *	bmp缓存首地址
 */
 
u8 *yuv_to_bmp(u8 *yuv, u32 w, u32 h)
{
	/*yuv4:2:2 ---> rgb24*/
	yuv_to_rgb24(yuv, w, h);

	BMPINFOHEADER bi;	//BMP文件头
	BMPFILEHEADER bf;	//BMP信息头
	
	/*初始化BMP头*/
        bi.biSize   = 0x28;	/*40*/;
        bi.biWidth  = w;
        bi.biHeight = h; //BMP图片从最后一个点开始扫描，显示时图片是倒着的，所以用-height，这样图片就正了   
        bi.biPlanes = 1;
        bi.biBitCount   = 24;
        bi.biCompression= 0;
        bi.biSizeImage  = w*h*3;  /*WIDTHBYTES(bi.biWidth * bi.biBitCount) * bi.biHeight*/;
        bi.biXPelsPerMeter = 0;
        bi.biYPelsPerMeter = 0;
        bi.biClrUsed      = 0;
        bi.biClrImportant = 0;

        bf.bfType = 0x4D42;	/*'B''M'*/
        bf.bfSize = 54 + bi.biSizeImage;
        bf.bfReserved= 0;
        bf.bfOffBits = 54;	/*偏移*/
        
        u8 *pbmp  = bmp24.buf;
        memcpy(pbmp, &bf.bfType, 14);
        pbmp += 14;
        memcpy(pbmp, &bi, 40);
        pbmp += 40;
	
        u8 *prgb24= rgb24.buf;

#if 1
	/*从下到上，从左到右，翻转拷贝*/
	prgb24 += (rgb24.len-1);   //指向rgb24 buf的尾
	int i, j;
	for(i = 0; i < h; i++)
	{
		for(j = 0; j < w; j++)
		{
			*pbmp++ = *prgb24--;
			*pbmp++ = *prgb24--;
			*pbmp++ = *prgb24--;
		}
	}
#endif	

    return bmp24.buf;
}

 /*
 *功能：获取bmp缓存的大小
 *输入：
 *输出：
 *	bmp缓存长度
 */
 
int get_bmp_len()
{
	return bmp24.len;
}
